package com.mpush.netty.http;

import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.mpush.api.Constants;
import com.mpush.tools.common.HashUtil;
import com.mpush.tools.config.CC;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;

/**
 * http工具类
 * 
 * @author gary.zhi
 * @date Jul 19, 2018 3:09:01 PM
 */
public final class NettyHttpClientUtils {

	private static final Logger LOGGER = LoggerFactory.getLogger(NettyHttpClientUtils.class);

	public static final String CONTENT_TYPE = "Content-Type";
	public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded; charset=";
	/**
	 * 调用时间
	 */
	public static final String CALL_TIMESTAMP = "callTimestamp";
	public static final String SIGN = "sign";

	private NettyHttpClientUtils() {

	}

	/**
	 * post 数据
	 * @param httpClient
	 * @param uri
	 * @param params
	 * @param callback
	 */
	public static void tryPost(HttpClient httpClient, String uri, Map<String, String> params, HttpCallback callback){
		try {
			post(httpClient,uri,params,callback);
		} catch (Exception e) {
			LOGGER.error("", e);
		}
	}

	/**
	 * post数据
	 * 
	 * @param httpClient
	 * @param uri
	 *            请求url
	 * @param params
	 *            请求参数
	 * @param callback:
	 *            回调(不能为null)
	 * @throws Exception
	 */
	public static void post(HttpClient httpClient, String uri, Map<String, String> params, HttpCallback callback)
			throws Exception {

		String queryString = encodeParams(params);
		String sign2 = getSign(params);
		byte[] body = queryString.getBytes();
		ByteBuf content = Unpooled.wrappedBuffer(body);

		FullHttpRequest request = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.valueOf("POST"), uri, content);
		request.headers().add(CONTENT_LENGTH, Integer.toString(body.length));
		request.headers().add(CONTENT_TYPE, CONTENT_TYPE_FORM + Constants.UTF_8.name());
		request.headers().add(CALL_TIMESTAMP, System.currentTimeMillis());
		request.headers().add(SIGN, sign2);

		httpClient.request(new RequestContext(request, callback));
	}
	
	

	private static String encodeParams(Map<String, String> params) {

		return Lists.newArrayList(params.keySet()).stream().filter(Objects::nonNull).sorted()
				.map(key -> String.join("=", encode(key), encode(params.get(key)))).collect(Collectors.joining("&"));
	}

	private static String encode(String str) {
		return encode(str, Constants.UTF_8.name());
	}

	private static String encode(String str, String encoding) {
		try {
			return URLEncoder.encode(str, encoding);
		} catch (UnsupportedEncodingException e) {
			LOGGER.error("url encoding error", e);
			return str;
		}
	}
	
	
	public static String getSign(Map<String, String> params) {
		 String linkString = Lists.newArrayList(params.keySet()).stream().filter(Objects::nonNull).sorted()
				.map(key -> String.join("=", key, params.get(key))).collect(Collectors.joining("&"));
		 return getSign(linkString);
	}
	
	/**
	 * 获取查询参数的签名
	 * 
	 * @param queryString
	 * @return
	 */
	public static String getSign(String queryString) {
		return HashUtil.sha1(queryString + CC.mp.api.signSecret);
	}

}
